/*
 * Copyright (c) 2008 niels
 *
 * This file is part of BlueRemote. Parts of this file are based 
 * on jRemote (http://sourceforge.net/projects/jremote/).
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with BlueRemote; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 */
package BlueRemote;

import java.io.IOException;
import java.io.OutputStream;

import java.util.Vector;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class Main_Midlet extends MIDlet implements CommandListener {
    private static final String[] elements = {"Right", "Left", "Up", "Down", "Enter"};
    private final List menu = new List("menu items", List.IMPLICIT, elements, null);
    private final static List commandList = new List("BlueRemote", List.IMPLICIT);
    private Command exitCommand;
    private Command connCommand;
    private Command scanCommand;
    public static Display display;
    private char[] data = {'1', '2', '3', '4', '5', '6'};
    private StreamConnection conn;
    private OutputStream os = null;
    public DiscoveryImpl discovery;
    private Command applyCommand;

    public void startApp() {
        display = Display.getDisplay(this);
        startDiscovery();
    //paintCanvas();
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
        closeConn();
        notifyDestroyed();
    }

    private void closeConn() {
        try {
            os.write((byte) data[5]);
            os.flush();
            os.close();
            conn.close();
        } catch (Exception e) {
        }
    }

    public void startDiscovery() {
        // Create buttons and add them to the list
        commandList.deleteAll();
        exitCommand = new Command("Exit", Command.EXIT, 2);
        commandList.addCommand(exitCommand);

        commandList.append("Searching ...", null);
        display.setCurrent(commandList);

        // Start actual discovery
        discovery = new DiscoveryImpl(this);
        discovery.doDiscoverDevice();
    }

    public void connectBluetooth(String string) {
        boolean err = false;

        // Try to connect
        if (!err) {
            try {
                // Build connection string and connect
                String conName = "btspp://" + string + ":1";
                log("Connecting to " + conName);
                conn = (StreamConnection) Connector.open(conName);
                os = conn.openOutputStream();
                os.write((byte) '0'); //data[0]
                os.flush();

            } catch (Exception e) {
                exitCommand = new Command("Exit", Command.EXIT, 2);
                commandList.addCommand(exitCommand);
                commandList.setCommandListener(this);
                log("Can't open connection: " + e);
                err = true;
            }
        }

        if (!err) {
            // 
            log("Connected successfully!");

            // Create buttons and add them to the menu
            exitCommand = new Command("Exit", Command.EXIT, 2);
            applyCommand = new Command("Apply", Command.SCREEN, 1);

            menu.addCommand(applyCommand);
            menu.addCommand(exitCommand);
            menu.setCommandListener(this);

            // Display menu and paint canvas
            display.setCurrent(menu);
            paintCanvas();

        }
    }

    public void commandAction(Command c, Displayable s) {
        // Exit
        if (c == exitCommand) {
            destroyApp(true);
            notifyDestroyed();
        }

        // Send selected
        if (menu.getSelectedIndex() < data.length) {
            try {
                os.write((byte) data[menu.getSelectedIndex()]);
                os.flush();
            } catch (Exception e) {

            }
        } else {
            System.err.println("unexpected choice...");
        }

    }

    public static void log(String message) {
        // Delete items of btlist and assign status (used for debugging)
        commandList.deleteAll();
        commandList.append(message, null);
        System.err.println(message);
    }

    private void paintCanvas() {
        // Create canvas
        Canvas canvas = new Canvas() {
            private int vi_height=getHeight();
            private int vi_width=getWidth();
            private int activeIcon = 0;
            private int i;

            public void paintElement(Graphics g, int element, boolean status) {
                // Set color
                if (status == true) {
                    // Status true, set color blue
                    g.setColor(0x0033FF);
                } else {
                    // Status false, set color grey
                    g.setColor(0xCCCCCC);
                }

                switch (element) {
                    // Arrow Right
                    case 1:
                        for (i = 0; i < 3; i++) {
                            g.drawLine((vi_width / 2) + 35, (vi_height / 2) + (10 - i), (vi_width / 2) + 25, (vi_height / 2) + (0 - i));
                            g.drawLine((vi_width / 2) + 35, (vi_height / 2) + (10 - i), (vi_width / 2) + 25, (vi_height / 2) + (20 - i));
                        }
                        break;
                    // Arrow Left
                    case 2:
                        for (i = 0; i < 3; i++) {
                            g.drawLine((vi_width / 2) - 35, (vi_height / 2) + (10 - i), (vi_width / 2) - 25, (vi_height / 2) + (0 - i));
                            g.drawLine((vi_width / 2) - 35, (vi_height / 2) + (10 - i), (vi_width / 2) - 25, (vi_height / 2) + (20 - i));
                        }
                        break;
                    // Arrow Top
                    case 3:
                        for (i = 0; i < 3; i++) {
                            g.drawLine((vi_width / 2), (vi_height / 2) - 25 - i, (vi_width / 2) - 10, (vi_height / 2) - 15 - i);
                            g.drawLine((vi_width / 2), (vi_height / 2) - 25 - i, (vi_width / 2) + 10, (vi_height / 2) - 15 - i);
                        }
                        break;
                    // Arrow Bottom
                    case 4:
                        for (i = 0; i < 3; i++) {
                            g.drawLine((vi_width / 2), (vi_height / 2) + 45 - i, (vi_width / 2) - 10, (vi_height / 2) + 35 - i);
                            g.drawLine((vi_width / 2), (vi_height / 2) + 45 - i, (vi_width / 2) + 10, (vi_height / 2) + 35 - i);
                        }
                        break;
                    // Circle (Enter)
                    case 5:
                        g.drawArc((vi_width / 2) - 5, (vi_height / 2) + 5, 10, 10, 0, 360);
                        g.drawArc((vi_width / 2) - 6, (vi_height / 2) + 4, 12, 12, 0, 360);
                        break;
                    default:
                    // nothing						
                }
            }

            public void paint(Graphics g) {
                // Create Icons
                for (int j = 1; j <= 5; j++) {
                    if (activeIcon == j) {
                        paintElement(g, j, true);
                    } else {
                        paintElement(g, j, false);
                    }
                }
            }

            public void setIcon(int icon) {
                // Send
                if (icon != 0) {
                    try {
                        os.write((byte) data[icon - 1]);
                        os.flush();
                    } catch (Exception e) {

                    }
                }
                // Set active icon and repaint
                activeIcon = icon;
                repaint();
            }

            public void keyPressed(int keyCode) {
                // Set icon depending on choice ...
                switch (getGameAction(keyCode)) {
                    case Canvas.RIGHT:
                        setIcon(1);
                        break;
                    case Canvas.LEFT:
                        setIcon(2);
                        break;
                    case Canvas.UP:
                        setIcon(3);
                        break;
                    case Canvas.DOWN:
                        setIcon(4);
                        break;
                    case Canvas.FIRE:
                        setIcon(5);
                        break;
                }

            }

            protected void keyReleased(int keyCode) {
                // Reset icon after the user releases a key
                setIcon(0);
            }
        };

        // Add buttons and listeners to canvas
        exitCommand = new Command("Exit", Command.EXIT, 2);
        canvas.addCommand(exitCommand);
        canvas.setCommandListener(this);
        display.setCurrent(canvas);
    }
    
    public void notifyEnquiryCompleted(Vector deviceNames) {
        if (deviceNames==null || deviceNames.isEmpty()) {
            Alert a = new Alert("no device found!",
                    "No Bluetooth has been found", null,AlertType.ERROR);
            scanCommand= new Command("try again", Command.SCREEN, 1);
            commandList.addCommand(scanCommand);
            commandList.setCommandListener(new btListener(this));
            display.setCurrent(a, commandList);
        } else {
            commandList.deleteAll();
            for (int i=0; i<deviceNames.size();i++) {
                commandList.append(deviceNames.elementAt(i).toString(), null);
            }
            connCommand = new Command("Connect", Command.SCREEN, 1);
            commandList.addCommand(connCommand);
            commandList.setCommandListener(new btListener(this));
            display.setCurrent(commandList);
        }
    }

    private class btListener implements CommandListener {
        Main_Midlet _parent=null;
        public btListener(Main_Midlet parent) {
            _parent=parent;
        }

        public void commandAction(Command c, Displayable s) {
            if (c == connCommand) {
                // Get the selected bt device and its friendly name
                int index=commandList.getSelectedIndex();
                Vector devices = discovery.getDevices();
                if (devices == null || devices.isEmpty()) {
                    // TODO show error message
                    return;
                }
                RemoteDevice btdevice = (RemoteDevice) devices.elementAt(index);
                try {
                    log("selected id: " + btdevice.getFriendlyName(true));
                } catch (IOException e) {
                    // TODO show error message
                    e.printStackTrace();
                }
                // Connect to the selected device
                connectBluetooth(btdevice.getBluetoothAddress());
            } else if (c == exitCommand) {
                _parent.destroyApp(false);
                
            } else if (c == scanCommand) {
                startDiscovery();
            }
            
        }
    }
}
